/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using DataModelException = System.Qizx.Api.DataModelException;
using EvaluationException = System.Qizx.Api.EvaluationException;
using Node = System.Qizx.Api.Node;
using QName = System.Qizx.Api.QName;
using SqlLikePattern = System.Qizx.Util.SqlLikePattern;
using StringPattern = System.Qizx.Util.StringPattern;
using IQName = System.Qizx.Xdm.IQName;
using EvalContext = System.Qizx.XQuery.EvalContext;
using Focus = System.Qizx.XQuery.Focus;
using XQType = System.Qizx.XQuery.XQType;
using XQValue = System.Qizx.XQuery.XQValue;
using Function = System.Qizx.XQuery.Fn.Function;
using Prototype = System.Qizx.XQuery.Fn.Prototype;
using Expression = System.Qizx.XQuery.Op.Expression;
namespace System.Qizx.XQuery.Ext
{
	
	/// <summary>  Implementation of function x:like.</summary>
	public class XfnLike:ExtensionFunction
	{
		public override Prototype[] Protos
		{
			get
			{
				return protos;
			}
			
		}
		private static QName qfname;
		private static Prototype[] protos;
		
		public class Exec:Function.BoolCall
		{
			public Expression subDomain; // supplem arg
			internal StringPattern previousPattern;
			internal string previous;
			internal EvalContext previousContext;
			
			protected internal virtual StringPattern preparePattern(string pattern, EvalContext context)
			{
				if (context == previousContext && pattern.Equals(previous))
					return previousPattern;
				previousPattern = new SqlLikePattern(pattern);
				previous = pattern;
				previousContext = context;
				return previousPattern;
			}
			
			public virtual StringPattern preparedPattern(EvalContext context)
			{
				if (args.Length > 1)
					subDomain = args[1];
				return preparePattern(args[0].evalAsString(null, context), context);
			}
			
			public override bool evalAsBoolean(Focus focus, EvalContext context)
			{
				StringPattern pattern = preparedPattern(context);
				
				try
				{
					if (args.Length > 1)
					{
						XQValue seq = args[1].eval(focus, context);
						// stop on first matching node:
						for (; seq.Next(); )
						{
							Node node = seq.GetNode();
							if (pattern.matches(node.StringValue))
								return true;
						}
						return false;
					}
					else
					{
						checkFocus(focus, context);
						return pattern.matches(focus.currentItem().GetNode().StringValue);
					}
				}
				catch (DataModelException e)
				{
					dmError(context, e);
					return false; // dummy
				}
			}
		}
		static XfnLike()
		{
			qfname = IQName.GetQName(EXTENSIONS_NS, "like");
			protos = new Prototype[]{new Prototype(qfname, XQType.BOOLEAN.opt, typeof(Exec)).arg("pattern", XQType.STRING).arg("context", XQType.NODE.star), new Prototype(qfname, XQType.BOOLEAN.opt, typeof(Exec)).arg("pattern", XQType.STRING)};
		}
	}
}